﻿using System;
using System.Reflection;

namespace AChance.Func
{
    public static class FunIdv
    {
        #region 获取个性化方法
        public static T Get<T>(T method, string idvNo = null) where T : Delegate =>
            Get<T>(method.Method.DeclaringType, method.Method.Name, idvNo);
        public static T Get<T>(Type declaringType, string methodName, string idvNo = null) where T : Delegate =>
           GetInfo(declaringType, methodName, idvNo).CreateDelegate(typeof(T)) as T;
        #endregion

        #region 获取个性化方法名称
        public static string GetName<T>(T method, string idvNo = null) where T : Delegate =>
            GetName(method.Method.DeclaringType, method.Method.Name, idvNo);
        public static string GetName(Type declaringType, string methodName, string idvNo = null) =>
            GetInfo(declaringType, methodName, idvNo).Name;
        #endregion

        #region 获取个性化方法信息
        public static MethodInfo GetInfo<T>(T method, string idvNo = null) where T : Delegate =>
            GetInfo(method.Method.DeclaringType, method.Method.Name, idvNo);
        public static MethodInfo GetInfo(Type declaringType, string methodName, string idvNo = null) =>
            declaringType.GetMethod(methodName + (idvNo ?? FunContext.OrganNo)) ?? declaringType.GetMethod(methodName) ?? throw new Exception("获取个性化方法失败");
        #endregion

        #region 执行个性化方法
        #region Func
        public static TResult Exec<TResult>(Func<TResult> method, string idvNo = null) =>
            Get(method, idvNo)();
        public static TResult Exec<T1, TResult>(Func<T1, TResult> method, T1 arg1, string idvNo = null) =>
            Get(method, idvNo)(arg1);
        public static TResult Exec<T1, T2, TResult>(Func<T1, T2, TResult> method, T1 arg1, T2 arg2, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2);
        public static TResult Exec<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> method, T1 arg1, T2 arg2, T3 arg3, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3);
        public static TResult Exec<T1, T2, T3, T4, TResult>(Func<T1, T2, T3, T4, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4);
        public static TResult Exec<T1, T2, T3, T4, T5, TResult>(Func<T1, T2, T3, T4, T5, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5);
        public static TResult Exec<T1, T2, T3, T4, T5, T6, TResult>(Func<T1, T2, T3, T4, T5, T6, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6);
        public static TResult Exec<T1, T2, T3, T4, T5, T6, T7, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        public static TResult Exec<T1, T2, T3, T4, T5, T6, T7, T8, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
        public static TResult Exec<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
        public static TResult Exec<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult>(Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, TResult> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
        #endregion

        #region Action
        public static void Exec(Action method, string idvNo = null) =>
            Get(method, idvNo)();
        public static void Exec<T1>(Action<T1> method, T1 arg1, string idvNo = null) =>
            Get(method, idvNo)(arg1);
        public static void Exec<T1, T2>(Action<T1, T2> method, T1 arg1, T2 arg2, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2);
        public static void Exec<T1, T2, T3>(Action<T1, T2, T3> method, T1 arg1, T2 arg2, T3 arg3, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3);
        public static void Exec<T1, T2, T3, T4>(Action<T1, T2, T3, T4> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4);
        public static void Exec<T1, T2, T3, T4, T5>(Action<T1, T2, T3, T4, T5> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5);
        public static void Exec<T1, T2, T3, T4, T5, T6>(Action<T1, T2, T3, T4, T5, T6> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6);
        public static void Exec<T1, T2, T3, T4, T5, T6, T7>(Action<T1, T2, T3, T4, T5, T6, T7> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7);
        public static void Exec<T1, T2, T3, T4, T5, T6, T7, T8>(Action<T1, T2, T3, T4, T5, T6, T7, T8> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8);
        public static void Exec<T1, T2, T3, T4, T5, T6, T7, T8, T9>(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9);
        public static void Exec<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10>(Action<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> method, T1 arg1, T2 arg2, T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7, T8 arg8, T9 arg9, T10 arg10, string idvNo = null) =>
            Get(method, idvNo)(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10);
        #endregion
        #endregion
    }
}